aboutsummaryrefslogtreecommitdiffstats
path: root/src/app/groups/[groupId]/expenses
diff options
context:
space:
mode:
authorSebastien Castiel <sebastien@castiel.me>2023-12-19 09:36:40 -0500
committerGitHub <noreply@github.com>2023-12-19 09:36:40 -0500
commit1e66efe5169dfad9a0c62ba42fbf31ce977bf49e (patch)
tree3c2ea81a8b2dd9ba989855de553d65b1bb90b7ad /src/app/groups/[groupId]/expenses
parent66ab0ff82bbcb3294d3a0fb84ae5ffcae9910e26 (diff)
Use modal dialogs for expense creation & edition (#10)
* First attemps at using route interception and modals * Remove route interception * Make it work * Use Vaul on small screens * Improve vaul
Diffstat (limited to 'src/app/groups/[groupId]/expenses')
-rw-r--r--src/app/groups/[groupId]/expenses/[expenseId]/edit/page.tsx42
-rw-r--r--src/app/groups/[groupId]/expenses/actions.ts28
-rw-r--r--src/app/groups/[groupId]/expenses/create/page.tsx27
-rw-r--r--src/app/groups/[groupId]/expenses/expense-list.tsx9
-rw-r--r--src/app/groups/[groupId]/expenses/expense-page.tsx19
-rw-r--r--src/app/groups/[groupId]/expenses/layout.tsx9
-rw-r--r--src/app/groups/[groupId]/expenses/page.tsx2
7 files changed, 64 insertions, 72 deletions
diff --git a/src/app/groups/[groupId]/expenses/[expenseId]/edit/page.tsx b/src/app/groups/[groupId]/expenses/[expenseId]/edit/page.tsx
deleted file mode 100644
index 188d08f..0000000
--- a/src/app/groups/[groupId]/expenses/[expenseId]/edit/page.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import { ExpenseForm } from '@/components/expense-form'
-import { deleteExpense, getExpense, getGroup, updateExpense } from '@/lib/api'
-import { expenseFormSchema } from '@/lib/schemas'
-import { Metadata } from 'next'
-import { notFound, redirect } from 'next/navigation'
-
-export const metadata: Metadata = {
- title: 'Edit expense',
-}
-
-export default async function EditExpensePage({
- params: { groupId, expenseId },
-}: {
- params: { groupId: string; expenseId: string }
-}) {
- const group = await getGroup(groupId)
- if (!group) notFound()
- const expense = await getExpense(groupId, expenseId)
- if (!expense) notFound()
-
- async function updateExpenseAction(values: unknown) {
- 'use server'
- const expenseFormValues = expenseFormSchema.parse(values)
- await updateExpense(groupId, expenseId, expenseFormValues)
- redirect(`/groups/${groupId}`)
- }
-
- async function deleteExpenseAction() {
- 'use server'
- await deleteExpense(expenseId)
- redirect(`/groups/${groupId}`)
- }
-
- return (
- <ExpenseForm
- group={group}
- expense={expense}
- onSubmit={updateExpenseAction}
- onDelete={deleteExpenseAction}
- />
- )
-}
diff --git a/src/app/groups/[groupId]/expenses/actions.ts b/src/app/groups/[groupId]/expenses/actions.ts
new file mode 100644
index 0000000..31bb2e7
--- /dev/null
+++ b/src/app/groups/[groupId]/expenses/actions.ts
@@ -0,0 +1,28 @@
+'use server'
+import { createExpense, deleteExpense, updateExpense } from '@/lib/api'
+import { expenseFormSchema } from '@/lib/schemas'
+import { revalidatePath } from 'next/cache'
+
+export async function createExpenseAction(groupId: string, values: unknown) {
+ 'use server'
+ const expenseFormValues = expenseFormSchema.parse(values)
+ await createExpense(expenseFormValues, groupId)
+ revalidatePath(`/groups/${groupId}`, 'layout')
+}
+
+export async function updateExpenseAction(
+ groupId: string,
+ expenseId: string,
+ values: unknown,
+) {
+ 'use server'
+ const expenseFormValues = expenseFormSchema.parse(values)
+ await updateExpense(groupId, expenseId, expenseFormValues)
+ revalidatePath(`/groups/${groupId}`, 'layout')
+}
+
+export async function deleteExpenseAction(groupId: string, expenseId: string) {
+ 'use server'
+ await deleteExpense(expenseId)
+ revalidatePath(`/groups/${groupId}`, 'layout')
+}
diff --git a/src/app/groups/[groupId]/expenses/create/page.tsx b/src/app/groups/[groupId]/expenses/create/page.tsx
deleted file mode 100644
index e603e59..0000000
--- a/src/app/groups/[groupId]/expenses/create/page.tsx
+++ /dev/null
@@ -1,27 +0,0 @@
-import { ExpenseForm } from '@/components/expense-form'
-import { createExpense, getGroup } from '@/lib/api'
-import { expenseFormSchema } from '@/lib/schemas'
-import { Metadata } from 'next'
-import { notFound, redirect } from 'next/navigation'
-
-export const metadata: Metadata = {
- title: 'Create expense',
-}
-
-export default async function ExpensePage({
- params: { groupId },
-}: {
- params: { groupId: string }
-}) {
- const group = await getGroup(groupId)
- if (!group) notFound()
-
- async function createExpenseAction(values: unknown) {
- 'use server'
- const expenseFormValues = expenseFormSchema.parse(values)
- await createExpense(expenseFormValues, groupId)
- redirect(`/groups/${groupId}`)
- }
-
- return <ExpenseForm group={group} onSubmit={createExpenseAction} />
-}
diff --git a/src/app/groups/[groupId]/expenses/expense-list.tsx b/src/app/groups/[groupId]/expenses/expense-list.tsx
index 798a5f8..adc6e7a 100644
--- a/src/app/groups/[groupId]/expenses/expense-list.tsx
+++ b/src/app/groups/[groupId]/expenses/expense-list.tsx
@@ -33,7 +33,9 @@ export function ExpenseList({
expense.isReimbursement && 'italic',
)}
onClick={() => {
- router.push(`/groups/${groupId}/expenses/${expense.id}/edit`)
+ router.push(`/groups/${groupId}/expenses/${expense.id}/edit`, {
+ scroll: false,
+ })
}}
>
<div>
@@ -66,7 +68,10 @@ export function ExpenseList({
{currency} {(expense.amount / 100).toFixed(2)}
</div>
<Button size="icon" variant="link" className="-my-2" asChild>
- <Link href={`/groups/${groupId}/expenses/${expense.id}/edit`}>
+ <Link
+ href={`/groups/${groupId}/expenses/${expense.id}/edit`}
+ scroll={false}
+ >
<ChevronRight className="w-4 h-4" />
</Link>
</Button>
diff --git a/src/app/groups/[groupId]/expenses/expense-page.tsx b/src/app/groups/[groupId]/expenses/expense-page.tsx
new file mode 100644
index 0000000..281c38b
--- /dev/null
+++ b/src/app/groups/[groupId]/expenses/expense-page.tsx
@@ -0,0 +1,19 @@
+import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card'
+import { ReactNode } from 'react'
+
+export function ExpensePage({
+ children,
+ title,
+}: {
+ children: ReactNode
+ title: ReactNode
+}) {
+ return (
+ <Card>
+ <CardHeader>
+ <CardTitle>{title}</CardTitle>
+ </CardHeader>
+ <CardContent>{children}</CardContent>
+ </Card>
+ )
+}
diff --git a/src/app/groups/[groupId]/expenses/layout.tsx b/src/app/groups/[groupId]/expenses/layout.tsx
new file mode 100644
index 0000000..cd65df9
--- /dev/null
+++ b/src/app/groups/[groupId]/expenses/layout.tsx
@@ -0,0 +1,9 @@
+import { ReactNode } from 'react'
+
+export default function GroupExpensesLayout({
+ children,
+}: {
+ children: ReactNode
+}) {
+ return <>{children}</>
+}
diff --git a/src/app/groups/[groupId]/expenses/page.tsx b/src/app/groups/[groupId]/expenses/page.tsx
index 5285cb8..64987a3 100644
--- a/src/app/groups/[groupId]/expenses/page.tsx
+++ b/src/app/groups/[groupId]/expenses/page.tsx
@@ -35,7 +35,7 @@ export default async function GroupExpensesPage({
</CardHeader>
<CardHeader>
<Button asChild size="icon">
- <Link href={`/groups/${groupId}/expenses/create`}>
+ <Link href={`/groups/${groupId}/expenses/create`} scroll={false}>
<Plus />
</Link>
</Button>